package public

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"time"

	"qianggougo/controller/common"
	"qianggougo/model"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

type Code2SessionRequest struct {
	AppID     string `json:"appid"`      // 小程序 AppID
	Secret    string `json:"secret"`     // 小程序 AppSecret
	JsCode    string `json:"js_code"`    // 前端传来的 code
	GrantType string `json:"grant_type"` // 固定值 "authorization_code"
}

type Code2SessionResponse struct {
	OpenID     string `json:"openid"`      // 用户唯一标识
	SessionKey string `json:"session_key"` // 会话密钥
	UnionID    string `json:"unionid"`     // 可选，用户在开放平台的唯一标识符
	ErrCode    int    `json:"errcode"`     // 错误码（0 表示成功）
	ErrMsg     string `json:"errmsg"`      // 错误信息
}

const (
	WeChatAPI = "https://api.weixin.qq.com/sns/jscode2session"
)

/**
 * 微信登录
 */
func WxLogin(c *gin.Context) {
	// 1. 获取前端传来的 code
	// jsCode := c.Query("code") // GET 参数方式
	// jsCode := c.PostForm("code")   // POST 表单方式
	// fmt.Println("打印code:", jsCode) // 输出到控制台
	// if jsCode == "" {
	// c.JSON(http.StatusBadRequest, gin.H{"error": "获取code失败"})
	// return
	// }

	// 定义接收JSON的结构体
	type Request struct {
		Code string `json:"code"` // 字段名和JSON key对应
	}

	// 解析JSON请求体
	var reqJson Request
	if err := c.ShouldBindJSON(&reqJson); err != nil {
		c.JSON(400, gin.H{"error": "无效的请求参数"})
		return
	}

	// 3. 获取code（现在可以正确获取）
	jsCode := reqJson.Code
	if jsCode == "" {
		c.JSON(400, gin.H{"error": "code不能为空"})
		return
	}
	// fmt.Println("打印code:", jsCode) // 输出到控制台

	// 2. 构造请求参数
	req := Code2SessionRequest{
		AppID:     "wxf49810e84ee7825b",               // 替换成你的 AppID
		Secret:    "c0d374166e73d3721753bd6aa82f3653", // 替换成你的 AppSecret
		JsCode:    jsCode,
		GrantType: "authorization_code",
	}

	// 3. 发送 HTTP GET 请求到微信 API
	client := &http.Client{}
	request, err := http.NewRequest("GET", WeChatAPI, nil)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "创建请求失败"})
		return
	}

	// 4. 添加 Query 参数
	q := request.URL.Query()
	q.Add("appid", req.AppID)
	q.Add("secret", req.Secret)
	q.Add("js_code", req.JsCode)
	q.Add("grant_type", req.GrantType)
	request.URL.RawQuery = q.Encode()

	// 5. 发送请求并解析响应
	resp, err := client.Do(request)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "调用微信API失败"})
		return
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "读取响应失败"})
		return
	}

	// 6. 解析微信返回的 JSON
	var sessionResp Code2SessionResponse
	if err := json.Unmarshal(body, &sessionResp); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "解析微信响应失败"})
		return
	}

	// 7. 检查微信返回的错误码
	if sessionResp.ErrCode != 0 {
		c.JSON(http.StatusUnauthorized, gin.H{
			"error":   "微信API错误",
			"errcode": sessionResp.ErrCode,
			"errmsg":  sessionResp.ErrMsg,
		})
		return
	}

	var user model.User
	userInfo := common.DB.Where("openid = ?", sessionResp.OpenID).First(&user)
	timestamp := int(time.Now().Unix()) // 获取当前时间戳
	if userInfo.Error != nil {          // 用户不存在，就增加用户，并加入到redis
		if userInfo.Error == gorm.ErrRecordNotFound {
			newUser := model.User{
				OpenID:       sessionResp.OpenID,
				SessionKey:   sessionResp.SessionKey,
				UnionID:      sessionResp.UnionID,
				Username:     fmt.Sprintf("%d", timestamp),
				Nickname:     fmt.Sprintf("%d", timestamp),
				LastAt:       time.Now(),
				ExpirationAt: timestamp + 60*60*24,
			}

			// 先创建用户记录
			if err := common.DB.Create(&newUser).Error; err != nil {
				c.JSON(500, gin.H{"error": "用户创建失败"})
				return
			}

			// 更新用户名和昵称
			updates := map[string]interface{}{
				"username": fmt.Sprintf("%d%d", timestamp, newUser.ID),
				"nickname": fmt.Sprintf("游客%d", newUser.ID),
				"token":    model.GenerateToken(newUser.ID, timestamp),
			}
			common.DB.Model(&newUser).Updates(updates)

			// 设置 Redis 键值（永久有效）
			if err := common.RDB.Set(context.Background(), strconv.Itoa(int(user.ID)), "0", 0).Err(); err != nil {
				log.Println("Redis 设置失败:", err)
			}

			user = newUser // 赋值给外部user变量
		}
	} else { // 用户存在，更新过期时间
		common.DB.Model(&user).Update("expiration_at", timestamp+60*60*24)
	}

	response := map[string]interface{}{
		"err": 0,
		"msg": "登录成功",
		"data": map[string]interface{}{
			"id":       user.ID,
			"nickname": user.Nickname,
			"username": user.Username,
			"avatar":   user.WxAvatar,
			"token":    user.Token,
			"lineup":   user.Lineup,
		},
	}

	// 输出JSON（Content-Type自动设置为application/json）
	c.JSON(http.StatusOK, response)
}
